home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / pstex / args.c < prev    next >
C/C++ Source or Header  |  1992-01-27  |  10KB  |  489 lines

  1. /*
  2.  * Argument parsing utilies.
  3.  *
  4.  * Neil Hunt (Neil%Teleos.com@ai.sri.com).
  5.  *
  6.  * Copyright (c) 1989 Teleos Research, Inc 1989.
  7.  * Copyright (c) 1989 Schlumberger Technologies, Inc 1989.
  8.  *
  9.  * Anyone can use this software in any manner they choose,
  10.  * including modification and redistribution, provided they make
  11.  * no charge for it, and these conditions remain unchanged.
  12.  *
  13.  * This program is distributed as is, with all faults (if any), and
  14.  * without any wrranty.  No author or distributor accepts responsibility
  15.  * to anyone for the consequences of using it, or for whether it serves any
  16.  * particular purpose at all, or any other reason.
  17.  *
  18.  * $Log:    args.c,v $
  19.  * Revision 1.2  89/02/20  11:21:31  neil
  20.  * Removed sunview.h include.
  21.  * 
  22.  * Revision 1.1  89/02/10  18:40:00  neil
  23.  * Initial revision
  24.  * 
  25.  * Taken from newlib library:
  26.  * Revision 1.6  88/08/08  17:54:07  hunt
  27.  * Removed prexit from a_ungetc in case where a_arg_ptr is NULL,
  28.  * as this case is indestinguishable from the case where a_arg_ptr
  29.  * pointed to the end of a word (to the application).
  30.  * 
  31.  * Revision 1.5  88/08/08  16:54:27  hunt
  32.  * Made a_arg_ptr etc non static, for special purpose applications such
  33.  * as parsing window arguments from the array.
  34.  * 
  35.  * Revision 1.4  88/05/11  16:44:11  hunt
  36.  * Added a_getc and a_ungetc functions.
  37.  * 
  38.  * Revision 1.3  88/03/17  18:29:54  hunt
  39.  * Completely rewritten; cleaner implementation.
  40.  * Added a_scaled function and some scale tables.
  41.  * 
  42.  * Revision 1.2  88/01/12  18:33:54  hunt
  43.  * Added a_arg(argc, argv) function for completeness and to hide a_arg_ptr.
  44.  * Currently a_arg_ptr is not made static, so as not to break old code.
  45.  * 
  46.  * Revision 1.1  87/11/24  11:20:01  hunt
  47.  * Initial revision
  48.  */
  49.  
  50. #include <stdio.h>
  51. #include <math.h>
  52. #include <string.h>
  53. #ifdef MSDOS
  54. #define MAXPATHLEN 255
  55. #include <stdlib.h>
  56. #include <process.h>
  57. #else
  58. #include <sys/param.h>        /* For MAXPATHLEN */
  59. #endif
  60. #include "std.h"
  61. #include "args.h"
  62.  
  63. static char *    a_arg_ptr = NULL;
  64. static int    a_arg_index = 0;
  65. static bool    a_escape_seen;
  66. char *        a_prog_name = "Anonymous";
  67.  
  68. /*
  69.  * a_next:
  70.  *    Returns the next flag in the command line,
  71.  *    or A_ARG if it is not a flag,
  72.  *    or A_END if there are no more args.
  73.  */
  74.  
  75. char
  76. a_next(argc, argv)
  77. int argc;
  78. char **argv;
  79. {
  80.     char opt;
  81.  
  82.     /*
  83.      * Checks.
  84.      */
  85.     if(argv == NULL || argc < 1)
  86.     {
  87.         fprintf(stderr, "a_arg: bad arguments\n");
  88.         exit(-1);
  89.     }
  90.  
  91.     /*
  92.      * Get program name on first call.
  93.      */
  94.     if(a_arg_index == 0)
  95.     {
  96.         a_prog_name = argv[0];
  97.         a_arg_index = 1;
  98.     }
  99.  
  100.     /*
  101.      * If there is part of the previous word left, then return it.
  102.      */
  103.     if(a_arg_ptr && *a_arg_ptr)
  104.         return *a_arg_ptr++;
  105.  
  106.     /*
  107.      * Return A_END after the end of the list.
  108.      */
  109.     if(a_arg_index >= argc)
  110.         return A_END;
  111.  
  112.     /*
  113.      * Look at the next word.
  114.      */
  115.     a_arg_ptr = argv[a_arg_index++];
  116.  
  117.     /*
  118.      * If we have seen the escape "--",
  119.      * or if the first char of the word * is not a '-',
  120.      * or if this is an isolated "-",
  121.      * then return ARG.
  122.      */
  123.     if(a_escape_seen || a_arg_ptr[0] != '-' || a_arg_ptr[1] == '\0')
  124.         return A_ARG;
  125.  
  126.     /*
  127.      * Look at the next char.
  128.      */
  129.     a_arg_ptr++;
  130.     opt = *a_arg_ptr++;
  131.  
  132.     /*
  133.      * If the next char is '-', then this is the escape.
  134.      * start over...
  135.      */
  136.     if(opt == '-')
  137.     {
  138.         a_escape_seen = TRUE;
  139.         return a_next(argc, argv);
  140.     }
  141.  
  142.     /*
  143.      * Otherwise, return this option.
  144.      */
  145.     return opt;
  146. }
  147.  
  148. /*
  149.  * a_arg:
  150.  *    Returns the next argument in the command line,
  151.  *    or NULL if there are no more args.
  152.  */
  153.  
  154. char *
  155. a_arg(argc, argv)
  156. int argc;
  157. char **argv;
  158. {
  159.     char *arg;
  160.  
  161.     /*
  162.      * Checks.
  163.      */
  164.     if(argv == NULL || argc < 1)
  165.     {
  166.         fprintf(stderr, "a_arg: bad arguments\n");
  167.         exit(-1);
  168.     }
  169.  
  170.     /*
  171.      * Get program name on first call.
  172.      */
  173.     if(a_arg_index == 0)
  174.     {
  175.         a_prog_name = argv[0];
  176.         a_arg_index = 1;
  177.     }
  178.  
  179.     /*
  180.      * If there is part of the previous word left, then return it.
  181.      */
  182.     if(a_arg_ptr && *a_arg_ptr)
  183.     {
  184.         arg = a_arg_ptr;
  185.         a_arg_ptr = NULL;
  186.         return arg;
  187.     }
  188.  
  189.     /*
  190.      * Return NULL after the end of the list.
  191.      */
  192.     if(a_arg_index >= argc)
  193.         return NULL;
  194.  
  195.     /*
  196.      * Return the next word.
  197.      */
  198.     return argv[a_arg_index++];
  199. }
  200.  
  201. /*
  202.  * a_getc:
  203.  *    Returns the next char in the current word,
  204.  *    or NULL if no more chars in word.
  205.  */
  206.  
  207. char
  208. a_getc(argc, argv)
  209. int argc;
  210. char **argv;
  211. {
  212.     return a_arg_ptr ? *a_arg_ptr++ : '\0';
  213. }
  214.  
  215. /*
  216.  * a_ungetc:
  217.  *    Pushes char back onto current word, if still available.
  218.  */
  219.  
  220. void
  221. a_ungetc(argc, argv ,c)
  222. int argc;
  223. char **argv;
  224. char c;
  225. {
  226.     if(a_arg_ptr)
  227.         *--a_arg_ptr = c;
  228. }
  229.  
  230. /*
  231.  * a_number:
  232.  *    Interpret the next word or part word as a number.
  233.  */
  234.  
  235. double
  236. a_number(argc, argv)
  237. int argc;
  238. char **argv;
  239. {
  240.     char *arg;
  241.  
  242.     if((arg = a_arg(argc, argv)) == NULL)
  243.         return 0.0;
  244.     else
  245.         return atof(arg);
  246. }
  247.  
  248. /*
  249.  * a_integer:
  250.  *    Interpret the next word or part word as an integer.
  251.  */
  252.  
  253. int
  254. a_integer(argc, argv)
  255. int argc;
  256. char **argv;
  257. {
  258.     char *arg;
  259.  
  260.     if((arg = a_arg(argc, argv)) == NULL)
  261.         return 0;
  262.     else
  263.         return atoi(arg);
  264. }
  265.  
  266. /*
  267.  * a_scale:
  268.  *    Interpret the next word of part word as a number with scale factor.
  269.  */
  270.  
  271. double
  272. a_scaled(argc, argv, scale_table)
  273. int argc;
  274. char **argv;
  275. struct scale_table *scale_table;
  276. {
  277.     char *arg;
  278.     double val;
  279.     char scale[100];
  280.     int scale_len;
  281.  
  282.     val = 0.0;
  283.  
  284.     /*
  285.      * Get the word.
  286.      */
  287.     if((arg = a_arg(argc, argv)) == NULL)
  288.         return 0.0;
  289.  
  290.     /*
  291.      * Read a double value and a units specifier.
  292.      * If no units, just return the value.
  293.      */
  294.     if(sscanf(arg, " %lf %s", &val, &scale[0]) < 2 || scale_table == NULL)
  295.         return val;
  296.  
  297.     /*
  298.      * Get the length of the scale string.
  299.      */
  300.     if((scale_len = strlen(scale)) <= 0)
  301.         return val;
  302.  
  303.     /*
  304.      * Try to match the units specifier.
  305.      */
  306.     for( ; scale_table->scale_name; scale_table++)
  307.         if(strncmp(scale_table->scale_name, scale, scale_len) == 0)
  308.             return val * scale_table->scale_factor;
  309.  
  310.     return val;
  311. }
  312.  
  313. /*
  314.  * Prepared scale tables.
  315.  */
  316.  
  317. struct scale_table scale_units[] =
  318. {
  319.     { "pico",    1e-12, },
  320.     { "p",        1e-12, },
  321.     { "nano",    1e-9, },
  322.     { "n",        1e-9, },
  323.     { "micro",    1e-6, },
  324.     { "u",        1e-6, },
  325.     { "milli",    1e-3, },
  326.     { "m",        1e-3, },
  327.  
  328.     { "kilo",    1e3, },
  329.     { "k",        1e3, },
  330.     { "Mega",    1e6, },
  331.     { "mega",    1e6, },
  332.     { "M",        1e6, },
  333.     { "Giga",    1e9, },
  334.     { "giga",    1e9, },
  335.     { "G",        1e9, },
  336.     { "Tera",    1e12, },
  337.     { "tera",    1e12, },
  338.     { "T",        1e12, },
  339.  
  340.     { (char *)NULL,    0.0, },
  341. };
  342.  
  343. #define    IN_PER_M    39.37007874
  344. #define M_PER_IN    0.0254
  345.  
  346. struct scale_table scale_inches[] =
  347. {
  348.     { "meters",    1.0 * IN_PER_M, },    /* Must come first */
  349.     { "metres",    1.0 * IN_PER_M, },
  350.     { "angstroms",    1e-10 * IN_PER_M, },
  351.     { "nm",        1e-9 * IN_PER_M, },
  352.     { "microns",    1e-6 * IN_PER_M, },
  353.     { "um",        1e-6 * IN_PER_M, },
  354.     { "millimeters",1e-3 * IN_PER_M, },
  355.     { "millimetres",1e-3 * IN_PER_M, },
  356.     { "mm",        1e-3 * IN_PER_M, },
  357.     { "centimeters",1e-2 * IN_PER_M, },
  358.     { "centimetres",1e-2 * IN_PER_M, },
  359.     { "cms",    1e-2 * IN_PER_M, },
  360.     { "kilometers",    1e3 * IN_PER_M, },
  361.     { "kilometres",    1e3 * IN_PER_M, },
  362.     { "km",        1e3 * IN_PER_M, },
  363.     { "nmile",    1852 * IN_PER_M, },
  364.  
  365.     { "mils",    0.001, },
  366.     { "inches",     1.0, },
  367.     { "\"",        1.0, },
  368.     { "feet",    12.0, },
  369.     { "foot",    12.0, },
  370.     { "ft",        12.0, },
  371.     { "\'",        12.0, },
  372.     { "yards",    36.0, },
  373.     { "yd",        36.0, },
  374.     { "rod",    198, },
  375.     { "rd",        198, },
  376.     { "miles",    63360, },
  377.  
  378.     { (char *)NULL,    0.0, },
  379. };
  380.  
  381. struct scale_table scale_meters[] =
  382. {
  383.     { "meters",    1.0, },
  384.     { "metres",    1.0, },
  385.     { "angstroms",    1e-10, },
  386.     { "nm",        1e-9, },
  387.     { "microns",    1e-6, },
  388.     { "um",        1e-6, },
  389.     { "millimeters",1e-3, },
  390.     { "millimetres",1e-3, },
  391.     { "mm",        1e-3, },
  392.     { "centimeters",1e-2, },
  393.     { "centimetres",1e-2, },
  394.     { "cms",    1e-2, },
  395.     { "kilometers",    1e3, },
  396.     { "kilometres",    1e3, },
  397.     { "km",        1e3, },
  398.     { "nmile",    1852, },
  399.  
  400.     { "mils",    0.001 * M_PER_IN, },
  401.     { "inches",     1.0 * M_PER_IN, },
  402.     { "\"",        1.0 * M_PER_IN, },
  403.     { "feet",    12.0 * M_PER_IN, },
  404.     { "foot",    12.0 * M_PER_IN, },
  405.     { "ft",        12.0 * M_PER_IN, },
  406.     { "\'",        12.0 * M_PER_IN, },
  407.     { "yards",    36.0 * M_PER_IN, },
  408.     { "yd",        36.0 * M_PER_IN, },
  409.     { "rod",    198 * M_PER_IN, },
  410.     { "rd",        198 * M_PER_IN, },
  411.     { "miles",    63360 * M_PER_IN, },
  412.  
  413.     { (char *)NULL,    0.0, },
  414. };
  415.  
  416. struct scale_table scale_seconds[] =
  417. {
  418.     { "us",            1e-6, },
  419.     { "microseconds",    1e-6, },
  420.     { "ms",            1e-3, },
  421.     { "milliseconds",    1e-3, },
  422.     { "seconds",        1.0, },
  423.     { "secs",        1.0, },
  424.     { "minutes",        60.0, },
  425.     { "mins",        60.0, },
  426.     { "hours",        3600.0, },
  427.     { "hrs",        3600.0, },
  428.     { "days",        86400.0, },
  429.     { "weeks",        604800.0, },
  430.     { "wks",        604800.0, },
  431.     { "years",        31556925.97, },
  432.     { "yrs",        31556925.97, },
  433.  
  434.     { (char *)NULL,    0.0, },
  435. };
  436.  
  437. #define KG_PER_LB    0.45359237
  438. #define LB_PER_KG    2.204622622
  439.  
  440. struct scale_table scale_kilograms[] =
  441. {
  442.     { "ounces",        0.0625 * KG_PER_LB, },
  443.     { "ozs",        0.0625 * KG_PER_LB, },
  444.     { "pounds",        1.0 * KG_PER_LB, },
  445.     { "lbs",        1.0 * KG_PER_LB, },
  446.     { "stones",        14.0 * KG_PER_LB, },
  447.     { "quarters",        28.0 * KG_PER_LB, },
  448.     { "hundredweights",    112.0 * KG_PER_LB, },
  449.     { "longtons",        2240.0 * KG_PER_LB, },
  450.     { "shorttons",        2000 * KG_PER_LB, },
  451.     { "tons",        2000 * KG_PER_LB, },
  452.  
  453.     { "milligrams",        1e-6, },
  454.     { "mgs",        1e-6, },
  455.     { "grams",        1e-3, },
  456.     { "gms",        1e-3, },
  457.     { "kilograms",        1.0, },
  458.     { "kgs",        1.0, },
  459.     { "tonnes",        1e3, },
  460.     { "metrictons",        1e3, },
  461.  
  462.     { (char *)NULL,    0.0, },
  463. };
  464.  
  465. struct scale_table scale_pounds[] =
  466. {
  467.     { "ounces",        0.0625, },
  468.     { "ozs",        0.0625, },
  469.     { "pounds",        1.0, },
  470.     { "lbs",        1.0, },
  471.     { "stones",        14.0, },
  472.     { "quarters",        28.0, },
  473.     { "hundredweights",    112.0, },
  474.     { "longtons",        2240.0, },
  475.     { "shorttons",        2000, },
  476.     { "tons",        2000, },
  477.  
  478.     { "milligrams",        1e-6 * LB_PER_KG, },
  479.     { "mgs",        1e-6 * LB_PER_KG, },
  480.     { "grams",        1e-3 * LB_PER_KG, },
  481.     { "gms",        1e-3 * LB_PER_KG, },
  482.     { "kilograms",        1.0 * LB_PER_KG, },
  483.     { "kgs",        1.0 * LB_PER_KG, },
  484.     { "tonnes",        1e3 * LB_PER_KG, },
  485.     { "metrictons",        1e3 * LB_PER_KG, },
  486.  
  487.     { (char *)NULL,    0.0, },
  488. };
  489.